<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Dao;

use App\Exception\CustomException;
use App\Job\IntegralJob;
use App\Kernel\Traits\DaoTrait;
use App\Kernel\Util\UserJwtInstance;
use App\Model\Goods;
use App\Model\GoodsSku;
use App\Model\IntegralDetail;
use App\Model\Order;
use App\Model\OrderItem;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;

/**
 * class
 *
 * @author 谢声强(861167322@qq.com)
 * @package App\Dao
 */
class OrderDao extends Dao
{

    /**
     * 订单状态：待支付
     *
     * @var int
     */
    const STATUS_UNPAID = 0;

    /**
     * 订单状态：已支付
     *
     * @var int
     */
    const STATUS_PAID = 1;

    /**
     * 订单状态：已发货
     *
     * @var int
     */
    const STATUS_DELIVERY = 2;

    /**
     * 订单状态：已完成
     *
     * @var int
     */
    const STATUS_RECEIVED = 3;

    /**
     * 订单状态：退款中
     *
     * @var int
     */
    const STATUS_IN_REFUND = 4;

    /**
     * 订单状态：已退款
     *
     * @var int
     */
    const STATUS_REFUND = 5;

    /**
     * 订单状态：已取消
     *
     * @var int
     */
    const STATUS_CANCEL = 6;

    /**
     * 取消订单限制状态
     *
     * @var array
     */
    const CANCEL_ORDER = [self::STATUS_PAID, self::STATUS_CANCEL, self::STATUS_DELIVERY, self::STATUS_RECEIVED, self::STATUS_IN_REFUND, self::STATUS_REFUND];

    /**
     * 确定收货限制状态
     *
     * @var array
     */
    const SURE_ORDER = [self::STATUS_UNPAID, self::STATUS_CANCEL, self::STATUS_RECEIVED, self::STATUS_IN_REFUND, self::STATUS_REFUND];

    /**
     * 积分类型：收入
     *
     * @var int
     */
    const INTEGRAL_INCOME = 1;

    /**
     * 积分类型：支出
     *
     * @var int
     */
    const INTEGRAL_EXPEND = 2;

    /**
     * 积分状态：消费
     *
     * @var int
     */
    const INTEGRAL_STATUS_CONSUME = 1;

    /**
     * 积分状态：分润
     *
     * @var int
     */
    const INTEGRAL_STATUS_RETAIL  = 2;

    use DaoTrait;

    /**
     * @inheritDoc
     */
    public function model(): string
    {
        return Order::class;
    }

    /**
     * update
     * @param $map
     * @param $data
     * @return mixed
     */
    public function update($map, $data)
    {
        return Order::query()->where(function($query) use ($map) { return queryWhere($query, $map); })->update($data);
    }

    /**
     * 根据条件获取收藏个数
     *
     * @param array $map
     * @return int
     */
    public function count(array $map = [])
    {
        return Order::query()->where(function($query) use ($map) { return queryWhere($query, $map); })->count();
    }

    /**
     *通过订单ID查询订单
     */
    public function getFirstOrder( $order_id )
    {
        return Order::query()->where('id', $order_id)->first();
    }

    /**
     * 通过订单编号获取订单
     * @param $order_no
     * @return mixed
     */
    public function getFirstOrderByNo($order_no)
    {
        return Order::query()
            ->where('order_no', $order_no)
            ->first();
    }

    /**
     * 创建订单
     * @param array $order
     * @param array $order_item
     * @param string $title
     * @param string $pic
     */
    public function createOrder(array $order, array $order_item, string $title, string $pic)
    {
        Db::beginTransaction();
        try {
            // 创建订单
            if (!self::makeModel()->create($order)) {
                throw new CustomException('ORDER.CREATE_FAIL');
            }
            $user = UserJwtInstance::instance()->build()->getUser();
            // 判断积分是否足够
            if ($order['integral'] > 0) {

                if ($user->integral < $order['integral']) {
                    $this->driver->push(new IntegralJob( $user->id ));
                    throw new CustomException('USER.INTEGER_NOT_ENOUGH');
                }

                // 扣除积分
                /*$user->integral = $user->integral - $order['integral'];
                if (!$user->save()) {
                    $this->driver->push(new IntegralJob( $user->id ));
                    throw new CustomException('USER.INTEGER_PAY_FAIL');
                }*/

                // 写入积分记录
                IntegralDetail::query()->create([
                    'user_id' => $user->id,
                    'status' => self::INTEGRAL_STATUS_CONSUME,
                    'type' => self::INTEGRAL_EXPEND,
                    'num' => $order['integral'],
                    'remark' => '兑换商品',
                    'order_no' => $order['order_no'],
                    'goods_name' => $title,
                    'goods_pic' => $pic,
                    'amount' => $order['price'],
                    'integral' => $order['integral'],
                ]);

            }
            // 创建订单items
            if (!OrderItem::query()->insert($order_item)) {
                throw new CustomException('ORDER.CREATE_ITEM_FAIL');
            }

            // 扣除SKU库存及商品库存
            foreach ($order_item as $item) {
                $goods_stock = Goods::query()->where('id', $item['goods_id'])->where('stock', '>', $item['num'])->decrement('stock', $item['num']);
                if (!$goods_stock) {
                    throw new CustomException('GOODS.STOCK_NOT_ENOUGH');
                }
                $sku_stock = GoodsSku::query()->where('id', $item['sku_id'])->where('stock', '>', $item['num'])->decrement('stock', $item['num']);
                if (!$sku_stock) {
                    throw new CustomException('GOODS.STOCK_NOT_ENOUGH');
                }
            }

            if( $order['price'] == 0 ) {
                self::update([
                    'order_no' => $order['order_no']
                ],[
                    'pay_time' => time(),
                    'pay_type' => 0,
                ]);
            }

            Db::commit();
            $this->driver->push(new IntegralJob( $user->id ));
        }
        catch (CustomException $e) {
            Db::rollBack();
            $this->error($e->getMessage());
        }
        catch (\Exception $e) {
            Db::rollBack();
            $this->error('COMMON.SYSTEM_ERROR');
        }
    }

    /**
     * 获取用户订单
     *
     * @param array $map
     * @return mixed
     */
    public function  get(array $map = [])
    {
        return Order::query()
            ->with('items:id,order_no,sku_picture,goods_name,price,num,sku_name,original_price,goods_id')
            ->where(function ($query) use ($map) {
                return queryWhere($query, $map);
            })
            ->where('user_id', uid())
            ->orderByDesc('created_at')
            ->select('id', 'order_no', 'price', 'status','integral')
            ->paginate(10);
    }

    /**
     * 订单详情
     *
     * @param int $order_id
     * @return mixed
     */
    public function detail(int $order_id)
    {
        $uid = uid();
        return Order::query()
            ->with(['items.goods', 'items.goodsSku'])
            ->where('user_id', $uid)
            ->where('id', $order_id)
            ->first();
    }


    /**
     * 通过条件获取用户单个订单记录
     *
     * @param array $map
     * @return mixed
     */
    public function getOrderByMap(array $map = [])
    {
        return Order::query()
            ->where(function ($query) use ($map) {
                return queryWhere($query, $map);
            })
        ->first();
    }

    /**
     * 通过条件获取用户单个订单记录
     * @param array $map
     * @param array|null $select
     * @return mixed
     */
    public function getUserOrderLogistics(array $map = [], array $select = null)
    {
        return Order::query()
            ->where(function ($query) use ($map) {
                return queryWhere($query, $map);
            })
            ->select($select)
            ->first();
    }

    /**
     * 获取订单通过map
     * @param array $map
     * @param string|null $sort
     * @param array|null $select
     * @param int|null $paginate
     * @return mixed
     */
    public function getOrdersByMapSelect(array $map = [], string $sort = null, array $select = null, int $paginate = null)
    {
        $model = self::makeModel();
        // 之间
        if (isset($map['between_field'])) {
            foreach ($map['between_field'] as $k => $value) {
                $model = $model->whereBetween($k, $value);
            }
            unset($map['between_field']);
        }
        // 或
        if (isset($map['or_field'])) {
            $model = $model->where(function (Builder $query) use($map) {
                foreach ($map['or_field'] as $field => $item) {
                    // 普通查询
                    if (!is_array($item)) {
                        $query->orWhere($field, $item);
                        continue;
                    }
                    // 其它方式
                    switch (strtolower($item[0])) {
                        case 'in':
                            $query->orWhereIn($field, $item[1]);
                            break;

                        default:
                            $query->orWhere($field, $item[0], $item[1]);
                    }
                }
            });

            unset($map['or_field']);
        }

        if (!empty($map)) {
            $model = $model->where(function ($query) use ($map) {
                return queryWhere($query, $map);
            });
        }
        if (null !== $sort) {
            $model = $model->orderByRaw($sort);
        }

        if (null !== $select) {
            $model = $model->select($select);
        }

        return $paginate > 0 ? $model->paginate($paginate) : $model->get();
    }

}